package xiaohuo.fancyring.util

import eos.moe.dragoncore.api.SlotAPI
import org.bukkit.entity.Entity
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import taboolib.common.platform.function.console
import taboolib.common.util.replaceWithOrder
import taboolib.expansion.dispatchCommandAsOp
import taboolib.platform.util.isNotAir
import taboolib.platform.util.sendLang
import xiaohuo.fancyring.config.ConfigManager
import xiaohuo.fancyring.data.RingData
import xiaohuo.fancyring.data.ShowRingData
import java.util.*

val showRingMap = hashMapOf<UUID, ShowRingData>()

fun Entity.showRing() {
    if (uniqueId in showRingMap) {
        if (showRingMap[uniqueId]!!.initialization) {
            sendLang("Initialization")
        } else {
            closeRing()
        }
    } else {
        if (this is Player) {
            val latest = getCoolDown("ShowRing", ConfigManager.showCoolDown)
            if (latest > 0) {
                sendLang("InCoolDown", latest)
                return
            }
            val allItem = mutableListOf<ItemStack>().apply {
                if (ConfigManager.showHand) {
                    equipment.itemInMainHand.let {
                        if (it.isNotAir()) {
                            this += it
                        }
                    }
                }
                ConfigManager.inventorySlot.forEach {
                    val item = inventory.getItem(it)
                    if (item.isNotAir()) {
                        this += item
                    }
                }
            }
            ConfigManager.dragonSlot.forEach {
                val item = SlotAPI.getCacheSlotItem(this, it)
                if (item.isNotAir()) {
                    allItem += item
                }
            }
            allItem.flatMap { it.getRing() }.let { it ->
                if (it.isNotEmpty()) {
                    showRingMap[uniqueId] = ShowRingData(this, it).also {
                        it.showToPlayer(getNearbyEntities(64.0, 64.0, 64.0).filterIsInstance<Player>() + this)
                    }
                    val hasExecute = mutableSetOf<RingData>()
                    it.forEach {
                        if (it !in hasExecute) {
                            it.executeOp.forEach { line ->
                                dispatchCommandAsOp(line.replaceWithOrder(name))
                            }
                            it.executeConsole.forEach { line ->
                                console().performCommand(line.replaceWithOrder(name))
                            }
                            hasExecute += it
                        }
                    }
                    setCoolDown("ShowRing")
                }
            }
        } else {
            if (isValid) {
                ConfigManager.monsterList.filter { it.match in name }.flatMap { it.ringList }.let { it ->
                    if (it.isNotEmpty()) {
                        showRingMap[uniqueId] = ShowRingData(this, it).also {
                            it.showToPlayer(getNearbyEntities(64.0, 64.0, 64.0).filterIsInstance<Player>())
                        }
                    }
                }
            }
        }
    }
}

fun UUID.getShowRingData(): ShowRingData? {
    return showRingMap[this]
}

fun Entity.closeRing() {
    showRingMap[uniqueId]?.closeShow()
    showRingMap -= uniqueId
}